package com.hghivln.pay;

import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.builder.AlipayTradeRefundRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.model.result.AlipayF2FRefundResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 支付类
 */
public class PayService {

    /**
     * 输出日志
     */
    static Log log = LogFactory.getLog("trade_pay");

    /**
     * 支付宝当面付的对象
     */
    static AlipayTradeService tradeService;

    /**
     * 初始化对象
     */
    static {
        // 一定要在创建AlipayTradeService之前调用Configs.init设置默认参数
        Configs.init("zfbinfo.properties");
        // AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    }

    // 商户操作员编号，添加此参数可以为商户操作员做销售统计
    static String operatorId = "test_operator_id";

    // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
    static String storeId = "test_store_id";

    // 支付超时，定义为120分钟
    static String timeoutExpress = "120m";

    /**
     * 支付的方法
     *
     * @param outTradeNo           (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，需保证商户系统端不能重复，建议通过数据库sequence生成，
     * @param subject              (必填) 订单标题，粗略描述用户的支付目的。如“喜士多（浦东店）消费”
     * @param totalAmount          (必填) 订单总金额，单位为元，不能超过1亿元
     *                             如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
     * @param undiscountableAmount (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段
     *                             如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
     * @param body                 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
     * @param notyifyUrl           支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
     * @return Map<String, Object>
     */
    public static Map<String, Object> pay(String outTradeNo,
                                          String subject,
                                          String totalAmount,
                                          String undiscountableAmount,
                                          String body,
                                          String notyifyUrl) {
        // 创建请求builder，设置请求参数
        //AlipayTradePayContentBuilder builder = new AlipayTradePayContentBuilder()
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject)
                .setTotalAmount(totalAmount)
                .setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount)
                .setBody(body)
                .setOperatorId(operatorId)
                .setStoreId(storeId)
                .setTimeoutExpress(timeoutExpress)
                .setNotifyUrl(notyifyUrl); //支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
        // 调用tradePay方法获取当面付应答
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        HashMap<String, Object> map = new HashMap<>();
        String msg;
        int code;
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");

                AlipayTradePrecreateResponse res = result.getResponse();
                // 得到支付码，本质是个url
                String qrCode = res.getQrCode();
                map.put("qrCode", qrCode);
                msg = "下单成功";
                code = 200;
                break;

            case FAILED:
                log.error("支付宝预下单失败!!!");
                msg = "下单失败";
                code = 500;
                break;

            case UNKNOWN:
                log.error("系统异常，预下单状态未知!!!");
                msg = "系统异常";
                code = 404;
                break;

            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                msg = "不支持的交易状态";
                code = 404;
                break;
        }
        map.put("msg", msg);
        map.put("code", code);
        return map;
    }


    /**
     * 退费请求
     *
     * @param outTradeNo   (必填) 外部订单号，需要退款交易的商户外部订单号
     * @param refundAmount (必填) 退款金额，该金额必须小于等于订单的支付金额，单位为元
     * @param refundReason (必填) 退款原因，可以说明用户退款原因，方便为商家后台提供统计
     * @param outRequestNo (可选，需要支持重复退货时必填) 商户退款请求号，相同支付宝交易号下的不同退款请求号对应同一笔交易的不同退款申请，
     *                     对于相同支付宝交易号下多笔相同商户退款请求号的退款交易，支付宝只会进行一次退款
     * @return Map<String, Object>
     */
    public static Map<String, Object> payback(String outTradeNo,
                                              String refundAmount,
                                              String refundReason,
                                              String outRequestNo) {
        // 创建请求builder，设置请求参数
        //AlipayTradePayContentBuilder builder = new AlipayTradePayContentBuilder()
        AlipayTradeRefundRequestBuilder builder = new AlipayTradeRefundRequestBuilder()
                .setOutTradeNo(outTradeNo)
                .setRefundAmount(refundAmount)
                .setRefundReason(refundReason)
                .setOutRequestNo(outRequestNo)
                .setStoreId(storeId);

        AlipayF2FRefundResult result = tradeService.tradeRefund(builder);
        System.out.println("result:" + result);
        HashMap<String, Object> map = new HashMap<>();
        String msg;
        int code;
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝退款成功: )");
                code = 200;
                msg = result.getResponse().getSubMsg();
                break;

            case FAILED:
                log.error("支付宝退款失败!!!");
                code = 500;
                msg = result.getResponse().getSubMsg();
                break;

            case UNKNOWN:
                log.error("系统异常，订单退款状态未知!!!");
                code = 500;
                msg = result.getResponse().getSubMsg();
                break;

            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                code = 500;
                msg = result.getResponse().getSubMsg();
                break;
        }
        map.put("code", code);
        map.put("msg", msg);
        return map;
    }
}
